﻿Public Class ExpressionNode
    Private Enum Precedence
        None = 11
        Unary = 10
        Power = 9
        Times = 8
        Div = 7
        IntDiv = 6
        Modulus = 5
        Plus = 4
    End Enum

    Public Expression As String
    Public LeftChild As ExpressionNode
    Public RightChild As ExpressionNode
    Public Op As String

    ' Constructor.
    Public Sub New(ByVal new_expression As String)
        ' Build the expression's parse tree.
        Expression = new_expression
        LeftChild = Nothing
        RightChild = Nothing
        ParseExpression()
    End Sub

    ' Return the text this node should display.
    Public ReadOnly Property Text() As String
        Get
            If Op = "" Then Return Expression
            Return Op
        End Get
    End Property

    ' Return the node's preorder traversal in a stack format.
    Public Function ShowStack(Optional ByVal indent As Integer = 0) As String
        Dim result As String = ""

        If Op = "" Then
            ' This is a literal.
            result = Space$(indent) & Expression
        Else
            ' It's not a literal.
            result &= Space$(indent) & Op
            If LeftChild IsNot Nothing Then result &= vbCrLf & LeftChild.ShowStack(indent + 2)
            If RightChild IsNot Nothing Then result &= vbCrLf & RightChild.ShowStack(indent + 2)
        End If
        Return result
    End Function

    ' Return the rebuilt expression.
    Public Function RebuildExpression() As String
        Dim result As String = ""

        If Op = "( )" Then
            ' Parentheses.
            result = "(" & LeftChild.RebuildExpression() & ")"
        ElseIf Op = "" Then
            ' This is a literal. Return it.
            result = Expression
        ElseIf RightChild Is Nothing Then
            ' A unary operator.
            result = Op & LeftChild.RebuildExpression()
        Else
            ' A binary operator.
            result = LeftChild.RebuildExpression() & Op & RightChild.RebuildExpression()
        End If

        Return result
    End Function

End Class
